#include <GLFW/glfw3.h>
#include <app/base_app.hpp>
#include <cassert>
#include <cstdio>
#include <glad/glad.h>

#include "core/log.h"

int main() {
    static struct GlfwInitHelper {
        GlfwInitHelper() {
            glfwSetErrorCallback(&GlfwInitHelper::_glfw_error_cb);
            if (glfwInit() != GLFW_TRUE) {
                assert(0 && "GLFW Init Error!");
            }
        }

        ~GlfwInitHelper() {
            glfwTerminate();
        }

    private:
        static void _glfw_error_cb(int code, const char *msg) {
            LOG_E("GLFW Error(%d): %s\n", code, msg);
        }
    } _;

    glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
//    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
//    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
//    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
//    glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);

    GLFWwindow *wnd = glfwCreateWindow(1440, 900, "Hello OpenGL", nullptr, nullptr);
    if (!wnd) {
        assert(0 && "Window creation failed!");
    }
    glfwMakeContextCurrent(wnd);
    glfwSwapInterval(1);
    gladLoadGLLoader((GLADloadproc) &glfwGetProcAddress);

    const auto versionStr = glGetString(GL_VERSION);
    LOG_I("OpenGL Version: %s", versionStr);

    {
//        auto app = CreateApp("TriangleApp", wnd, {});
//        auto app = CreateApp("WaveApp", wnd, {});
//        auto app = CreateApp("InterpolationApp", wnd, {});
//        auto app = CreateApp("CubeApp", wnd, {});
//        auto app = CreateApp("FpgaControl", wnd, {});
//        auto app = CreateApp("ZViewControl", wnd, {});
        auto app = CreateApp("ZUSWaveApp", wnd, {});
        app->OnInitialize();

        while (!glfwWindowShouldClose(wnd)) {
            glfwPollEvents();
            app->Update();
        }
        app->OnCleanup();
    }

    glfwDestroyWindow(wnd);
}
